/* 该文件是 libschrift 库的一部分。
 *
 * 版权所有 © 2019-2022 Thomas Oltmann 及贡献者
 *
 * 特此授予任何人在不支付费用的情况下，出于任何目的使用、复制、修改和/或分发本软件的权利，
 * 前提是上述版权声明和本许可声明出现在所有副本中。
 * 
 * 本软件按"原样"提供，作者不对本软件作出任何明示或暗示的保证，
 * 包括但不限于适销性和特定用途适用性的保证。在任何情况下，作者均不承担
 * 因使用本软件而产生的任何直接、间接、特殊、偶然或 CONSEQUENTIAL 损害，
 * 或因使用、数据或利润损失而产生的任何损害，无论是基于合同、疏忽还是其他侵权行为，
 * 均与本软件的使用或性能有关。 */

#include <assert.h>     // 断言宏，用于调试时检查条件
#include <errno.h>      // 错误码定义
#include <math.h>       // 数学函数（如fabs、floor、ceil等）
#include <stdio.h>      // 标准输入输出函数
#include <stdlib.h>     // 内存分配、释放等通用函数
#include <string.h>     // 字符串操作函数

#if defined(_MSC_VER)
# define restrict __restrict  // MSVC编译器的restrict关键字别名，用于指针优化
#endif

#if defined(_WIN32)
# define WIN32_LEAN_AND_MEAN 1  // 减少Windows头文件包含量，只保留核心功能
# include <windows.h>           // Windows系统API头文件（文件映射等功能）
#else
# define _POSIX_C_SOURCE 1      // 启用POSIX标准函数
# include <fcntl.h>             // 文件控制函数（open等）
# include <sys/mman.h>          // 内存映射函数（mmap等）
# include <sys/stat.h>          // 文件状态函数（fstat等）
# include <unistd.h>            // Unix标准函数（close等）
#endif

#include "schrift.h"  // libschrift库核心头文件，包含对外接口定义

#define SCHRIFT_VERSION "0.10.2"  // 库版本号定义

// TTF字体文件魔术数（用于验证文件格式）
#define FILE_MAGIC_ONE             0x00010000  // 魔术数1
#define FILE_MAGIC_TWO             0x74727565  // 魔术数2（ASCII: 'true'）

// 字距调整相关标志（TTF kern表使用）
#define HORIZONTAL_KERNING         0x01  // 水平字距调整标志
#define MINIMUM_KERNING            0x02  // 最小字距调整标志
#define CROSS_STREAM_KERNING       0x04  // 交叉流（垂直）字距调整标志
#define OVERRIDE_KERNING           0x08  // 覆盖原有字距调整标志

// 轮廓点相关标志（TTF glyf表使用）
#define POINT_IS_ON_CURVE          0x01  // 标记该点在曲线上（非控制点）
#define X_CHANGE_IS_SMALL          0x02  // X坐标变化量较小（1字节存储）
#define Y_CHANGE_IS_SMALL          0x04  // Y坐标变化量较小（1字节存储）
#define REPEAT_FLAG                0x08  // 重复标志（后续字节表示重复次数）
#define X_CHANGE_IS_ZERO           0x10  // X坐标无变化
#define X_CHANGE_IS_POSITIVE       0x10  // X坐标变化为正（与X_CHANGE_IS_ZERO互斥）
#define Y_CHANGE_IS_ZERO           0x20  // Y坐标无变化
#define Y_CHANGE_IS_POSITIVE       0x20  // Y坐标变化为正（与Y_CHANGE_IS_ZERO互斥）

// TTF字体解析时的偏移量和缩放标志（复合字形使用）
#define OFFSETS_ARE_LARGE          0x001  // 偏移量为16位（否则8位）
#define ACTUAL_XY_OFFSETS          0x002  // 使用实际XY偏移量（而非点匹配）
#define GOT_A_SINGLE_SCALE         0x008  // 单个缩放因子（X/Y轴缩放相同）
#define THERE_ARE_MORE_COMPONENTS  0x020  // 存在更多复合字形组件
#define GOT_AN_X_AND_Y_SCALE       0x040  // X和Y轴单独缩放
#define GOT_A_SCALE_MATRIX         0x080  // 使用2x2缩放矩阵（支持旋转/倾斜）

/* 通用宏定义 */
#define MIN(a, b) ((a) < (b) ? (a) : (b))  // 取两个值中的最小值
#define SIGN(x)   (((x) > 0) - ((x) < 0))    // 取数值符号（正数返回1，负数返回-1，0返回0）
/* 栈/堆动态分配宏：如果分配数量小于阈值则用栈分配，否则用堆分配（calloc初始化） */
#define STACK_ALLOC(var, type, thresh, count) \
type var##_stack_[thresh]; \
var = (count) <= (thresh) ? var##_stack_ : calloc(sizeof(type), count);
/* 释放栈/堆分配的内存：仅当变量不在栈上时调用free */
#define STACK_FREE(var) \
if (var != var##_stack_) free(var);

// 字体数据源类型枚举（标记字体数据来源）
enum { 
    SrcMapping,  // 内存映射（从文件加载）
    SrcUser      // 用户提供（直接传入内存块）
};

/* 结构体声明 */
typedef struct Point   Point;     // 点坐标结构体
typedef struct Line    Line;      // 线段结构体
typedef struct Curve   Curve;     // 贝塞尔曲线结构体
typedef struct Cell    Cell;      // 栅格单元结构体（用于光栅化）
typedef struct Outline Outline;   // 字形轮廓结构体
typedef struct Raster  Raster;    // 光栅化缓冲区结构体

// 点坐标结构体（双精度浮点数，用于高精度计算）
struct Point { 
    double x;  // X坐标
    double y;  // Y坐标
};

// 线段结构体（存储轮廓中点的索引范围）
struct Line  { 
    uint_least16_t beg;  // 起始点索引
    uint_least16_t end;  // 结束点索引
};

// 贝塞尔曲线结构体（二次贝塞尔曲线：起点-控制点-终点）
struct Curve { 
    uint_least16_t beg;  // 起始点索引
    uint_least16_t end;  // 结束点索引
    uint_least16_t ctrl; // 控制点索引
};

// 栅格单元结构体（用于存储光栅化过程中的覆盖面积和累积值）
struct Cell  { 
    double area;  // 覆盖面积（用于计算灰度值）
    double cover; // 覆盖累积值（用于扫描线积分）
};

// 字形轮廓结构体（存储解析后的点、线段、曲线数据）
struct Outline
{
    Point *points;         // 点数组
    Curve *curves;         // 曲线数组
    Line  *lines;          // 线段数组
    uint_least16_t numPoints;  // 实际点数量
    uint_least16_t capPoints;  // 点数组容量（可扩展）
    uint_least16_t numCurves;  // 实际曲线数量
    uint_least16_t capCurves;  // 曲线数组容量
    uint_least16_t numLines;   // 实际线段数量
    uint_least16_t capLines;   // 线段数组容量
};

// 光栅化缓冲区结构体（存储栅格化后的中间数据）
struct Raster
{
    Cell *cells;  // 栅格单元数组
    int   width;  // 缓冲区宽度（像素数）
    int   height; // 缓冲区高度（像素数）
};

// 字体核心结构体（存储字体文件数据、解析后的元信息）
struct SFT_Font
{
    const uint8_t *memory;    // 字体文件内存指针
    uint_fast32_t  size;      // 字体文件大小（字节）
#if defined(_WIN32)
    HANDLE         mapping;   // Windows文件映射句柄（仅Windows平台使用）
#endif
    int            source;    // 数据源类型（SrcMapping/SrcUser）
    
    uint_least16_t unitsPerEm;// 每Em单位的设计单位数（字体设计缩放基准）
    int_least16_t  locaFormat;// loca表格式（0=16位偏移，1=32位偏移）
    uint_least16_t numLongHmtx;// 长水平度量数量（hmtx表中完整度量的字形数）
};

/* 函数声明 */
/* 通用工具函数 */
static void *reallocarray(void *optr, size_t nmemb, size_t size); // 安全内存重分配（避免溢出）
static inline int fast_floor(double x); // 快速向下取整（比标准floor更快）
static inline int fast_ceil (double x); // 快速向上取整（比标准ceil更快）
/* 文件加载函数 */
static int  map_file  (SFT_Font *font, const char *filename); // 映射字体文件到内存（跨平台）
static void unmap_file(SFT_Font *font); // 解除内存映射（跨平台）
static int  init_font (SFT_Font *font); // 初始化字体元信息（解析head/hhea表）
/* 简单数学运算函数 */
static Point midpoint(Point a, Point b); // 计算两点中点
static void transform_points(unsigned int numPts, Point *points, double trf[6]); // 应用仿射变换到点集
static void clip_points(unsigned int numPts, Point *points, int width, int height); // 裁剪点到指定矩形区域
/* 轮廓数据结构管理函数 */
static int  init_outline(Outline *outl); // 初始化轮廓结构体（分配初始内存）
static void free_outline(Outline *outl); // 释放轮廓结构体内存
static int  grow_points (Outline *outl); // 扩展点数组容量（2倍扩容）
static int  grow_curves (Outline *outl); // 扩展曲线数组容量（2倍扩容）
static int  grow_lines  (Outline *outl); // 扩展线段数组容量（2倍扩容）
/* TTF解析工具函数 */
static inline int is_safe_offset(SFT_Font *font, uint_fast32_t offset, uint_fast32_t margin); // 检查偏移量是否安全（避免越界）
static void *csearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); // 带进位的二分查找
static int  cmpu16(const void *a, const void *b); // 16位无符号整数比较函数（用于二分查找）
static int  cmpu32(const void *a, const void *b); // 32位无符号整数比较函数（用于二分查找）
static inline uint_least8_t  getu8 (SFT_Font *font, uint_fast32_t offset); // 从字体内存读取8位无符号整数
static inline int_least8_t   geti8 (SFT_Font *font, uint_fast32_t offset); // 从字体内存读取8位有符号整数
static inline uint_least16_t getu16(SFT_Font *font, uint_fast32_t offset); // 从字体内存读取16位无符号整数（大端）
static inline int_least16_t  geti16(SFT_Font *font, uint_fast32_t offset); // 从字体内存读取16位有符号整数（大端）
static inline uint_least32_t getu32(SFT_Font *font, uint_fast32_t offset); // 从字体内存读取32位无符号整数（大端）
static int gettable(SFT_Font *font, char tag[4], uint_fast32_t *offset); // 根据标签查找TTF表的偏移量
/* 编码点到字形ID转换函数 */
static int  cmap_fmt4(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, uint_fast32_t *glyph); // 解析格式4的cmap表（Unicode BMP）
static int  cmap_fmt6(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, uint_fast32_t *glyph); // 解析格式6的cmap表（连续编码范围）
static int  cmap_fmt12_13(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, uint_fast32_t *glyph, int which); // 解析格式12/13的cmap表（支持非BMP）
static int  glyph_id(SFT_Font *font, SFT_UChar charCode, uint_fast32_t *glyph); // 编码点转换为字形ID（自动选择cmap表）
/* 字形度量查询函数 */
static int  hor_metrics(SFT_Font *font, uint_fast32_t glyph, int *advanceWidth, int *leftSideBearing); // 获取字形水平度量（前进宽度、左bearing）
static int  glyph_bbox(const SFT *sft, uint_fast32_t outline, int box[4]); // 获取字形边界框（转换为渲染坐标）
/* 轮廓解码函数 */
static int  outline_offset(SFT_Font *font, uint_fast32_t glyph, uint_fast32_t *offset); // 获取字形轮廓在glyf表中的偏移量
static int  simple_flags(SFT_Font *font, uint_fast32_t *offset, uint_fast16_t numPts, uint8_t *flags); // 解析简单字形的点标志
static int  simple_points(SFT_Font *font, uint_fast32_t offset, uint_fast16_t numPts, uint8_t *flags, Point *points); // 解析简单字形的点坐标
static int  decode_contour(uint8_t *flags, uint_fast16_t basePoint, uint_fast16_t count, Outline *outl); // 解码单个轮廓（转换为线段/曲线）
static int  simple_outline(SFT_Font *font, uint_fast32_t offset, unsigned int numContours, Outline *outl); // 解码简单字形轮廓
static int  compound_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl); // 解码复合字形轮廓（递归解析组件）
static int  decode_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl); // 通用轮廓解码（自动区分简单/复合字形）
/* 曲线细分函数 */
static int  is_flat(Outline *outl, Curve curve); // 判断曲线是否足够平坦（可近似为线段）
static int  tesselate_curve(Curve curve, Outline *outl); // 细分单条曲线为线段
static int  tesselate_curves(Outline *outl); // 细分所有曲线为线段
/* 轮廓光栅化函数 */
static void draw_line(Raster buf, Point origin, Point goal); // 绘制线段到光栅缓冲区（自定义射线投射算法）
static void draw_lines(Outline *outl, Raster buf); // 绘制所有线段到光栅缓冲区
/* 后处理函数 */
static void post_process(Raster buf, uint8_t *image); // 光栅数据后处理（生成最终灰度图像）
/* 字形渲染函数 */
static int  render_outline(Outline *outl, double transform[6], SFT_Image image); // 渲染轮廓到图像（包含变换、裁剪、细分、光栅化）

/* 函数实现 */

// 返回库版本号
const char *
sft_version(void)
{
    return SCHRIFT_VERSION;
}

/* 从用户提供的内存块加载字体。
 * 参数：mem - 字体数据内存指针，size - 内存块大小
 * 返回：成功返回SFT_Font指针，失败返回NULL */
SFT_Font *
sft_loadmem(const void *mem, size_t size)
{
    SFT_Font *font;
    // 检查大小是否超过32位无符号整数上限（避免溢出）
    if (size > UINT32_MAX) {
        return NULL;
    }
    // 分配字体结构体内存并初始化为0
    if (!(font = calloc(1, sizeof *font))) {
        return NULL;
    }
    // 设置字体数据指针、大小和数据源类型
    font->memory = mem;
    font->size   = (uint_fast32_t) size;
    font->source = SrcUser;
    // 初始化字体元信息（解析head/hhea表）
    if (init_font(font) < 0) {
        sft_freefont(font); // 初始化失败，释放资源
        return NULL;
    }
    return font;
}

/* 从文件系统加载字体（通过内存映射方式）。
 * 参数：filename - 字体文件路径
 * 返回：成功返回SFT_Font指针，失败返回NULL */
SFT_Font *
sft_loadfile(char const *filename)
{
    SFT_Font *font;
    // 分配字体结构体内存并初始化为0
    if (!(font = calloc(1, sizeof *font))) {
        return NULL;
    }
    // 映射文件到内存
    if (map_file(font, filename) < 0) {
        free(font); // 映射失败，释放结构体
        return NULL;
    }
    // 初始化字体元信息
    if (init_font(font) < 0) {
        sft_freefont(font); // 初始化失败，释放资源
        return NULL;
    }
    return font;
}

/* 释放字体资源。
 * 参数：font - 要释放的字体结构体指针 */
void
sft_freefont(SFT_Font *font)
{
    if (!font) return; // 空指针直接返回
    /* 仅当数据源是内存映射时，解除映射 */
    if (font->source == SrcMapping)
        unmap_file(font);
    free(font); // 释放字体结构体本身
}

/* 获取字体行度量信息（升部、降部、行间距）。
 * 参数：sft - 渲染配置，metrics - 输出行度量结构体
 * 返回：成功返回0，失败返回-1 */
int
sft_lmetrics(const SFT *sft, SFT_LMetrics *metrics)
{
    double factor;          // 缩放因子（设计单位转渲染单位）
    uint_fast32_t hhea;     // hhea表的偏移量
    memset(metrics, 0, sizeof *metrics); // 初始化输出结构体为0
    // 查找hhea表（水平度量表头）
    if (gettable(sft->font, "hhea", &hhea) < 0)
        return -1;
    // 检查hhea表是否有足够长度（至少36字节）
    if (!is_safe_offset(sft->font, hhea, 36))
        return -1;
    // 计算缩放因子（渲染Y轴缩放 / 每Em单位数）
    factor = sft->yScale / sft->font->unitsPerEm;
    // 读取并缩放升部、降部、行间距（hhea表偏移4、6、8处）
    metrics->ascender  = geti16(sft->font, hhea + 4) * factor;
    metrics->descender = geti16(sft->font, hhea + 6) * factor;
    metrics->lineGap   = geti16(sft->font, hhea + 8) * factor;
    return 0;
}

/* 编码点转换为字形ID。
 * 参数：sft - 渲染配置，codepoint - Unicode编码点，glyph - 输出字形ID
 * 返回：成功返回0，失败返回-1 */
int
sft_lookup(const SFT *sft, SFT_UChar codepoint, SFT_Glyph *glyph)
{
    return glyph_id(sft->font, codepoint, glyph);
}

/* 获取字形度量信息（前进宽度、左bearing、边界框等）。
 * 参数：sft - 渲染配置，glyph - 字形ID，metrics - 输出字形度量结构体
 * 返回：成功返回0，失败返回-1 */
int
sft_gmetrics(const SFT *sft, SFT_Glyph glyph, SFT_GMetrics *metrics)
{
    int adv, lsb;           // 前进宽度、左bearing（设计单位）
    double xScale = sft->xScale / sft->font->unitsPerEm; // X轴缩放因子
    uint_fast32_t outline;  // 字形轮廓偏移量
    int bbox[4];            // 字形边界框（渲染坐标）

    memset(metrics, 0, sizeof *metrics); // 初始化输出结构体为0

    // 获取字形水平度量（前进宽度、左bearing）
    if (hor_metrics(sft->font, glyph, &adv, &lsb) < 0)
        return -1;
    // 缩放前进宽度和左bearing（添加X轴偏移）
    metrics->advanceWidth    = adv * xScale;
    metrics->leftSideBearing = lsb * xScale + sft->xOffset;

    // 获取字形轮廓偏移量
    if (outline_offset(sft->font, glyph, &outline) < 0)
        return -1;
    if (!outline)
        return 0; // 无轮廓数据（空白字形）
    // 获取字形边界框（转换为渲染坐标）
    if (glyph_bbox(sft, outline, bbox) < 0)
        return -1;
    // 计算最小宽度、高度和Y轴偏移
    metrics->minWidth  = bbox[2] - bbox[0] + 1;
    metrics->minHeight = bbox[3] - bbox[1] + 1;
    // 根据Y轴方向标志计算Y轴偏移（SFT_DOWNWARD_Y表示Y轴向下）
    metrics->yOffset   = sft->flags & SFT_DOWNWARD_Y ? -bbox[3] : bbox[1];

    return 0;
}

/* 获取两个字形之间的字距调整值。
 * 参数：sft - 渲染配置，leftGlyph - 左侧字形ID，rightGlyph - 右侧字形ID，kerning - 输出字距调整值
 * 返回：成功返回0，失败返回-1 */
int
sft_kerning(const SFT *sft, SFT_Glyph leftGlyph, SFT_Glyph rightGlyph,
            SFT_Kerning *kerning)
{
    void *match;                // 二分查找匹配结果
    uint_fast32_t offset;       // kern表偏移量
    unsigned int numTables, numPairs, length, format, flags; // kern表参数
    int value;                  // 字距调整值（设计单位）
    uint8_t key[4];             // 字形对查找键（左高8位、左低8位、右高8位、右低8位）

    memset(kerning, 0, sizeof *kerning); // 初始化输出结构体为0

    // 查找kern表（字距调整表），不存在则返回0（无调整）
    if (gettable(sft->font, "kern", &offset) < 0)
        return 0;

    /* 读取kern表头部 */
    if (!is_safe_offset(sft->font, offset, 4))
        return -1;
    if (getu16(sft->font, offset) != 0)
        return 0; // 版本号不为0，不支持
    numTables = getu16(sft->font, offset + 2); // 子表数量
    offset += 4; // 偏移量指向第一个子表

    // 遍历所有kern子表
    while (numTables > 0) {
        /* 读取子表头部 */
        if (!is_safe_offset(sft->font, offset, 6))
            return -1;
        length = getu16(sft->font, offset + 2); // 子表长度
        format = getu8 (sft->font, offset + 4); // 子表格式
        flags  = getu8 (sft->font, offset + 5); // 子表标志
        offset += 6; // 偏移量指向子表数据

        // 仅处理格式0、水平字距调整、非最小字距调整的子表
        if (format == 0 && (flags & HORIZONTAL_KERNING) && !(flags & MINIMUM_KERNING)) {
            /* 读取格式0子表头部 */
            if (!is_safe_offset(sft->font, offset, 8))
                return -1;
            numPairs = getu16(sft->font, offset); // 字形对数量
            offset += 8; // 偏移量指向字形对数据
            /* 构建查找键（4字节：左字形ID高8位、低8位，右字形ID高8位、低8位） */
            key[0] = (leftGlyph  >> 8) & 0xFF;
            key[1] =  leftGlyph  & 0xFF;
            key[2] = (rightGlyph >> 8) & 0xFF;
            key[3] =  rightGlyph & 0xFF;
            // 二分查找字形对
            if ((match = bsearch(key, sft->font->memory + offset,
                numPairs, 6, cmpu32)) != NULL) {
                // 读取字距调整值（字形对数据的后2字节）
                value = geti16(sft->font, (uint_fast32_t) ((uint8_t *) match - sft->font->memory + 4));
                // 根据标志判断是水平还是垂直调整
                if (flags & CROSS_STREAM_KERNING) {
                    kerning->yShift += value;
                } else {
                    kerning->xShift += value;
                }
            }

        }

        offset += length; // 偏移量指向下一个子表
        --numTables;
    }

    // 缩放字距调整值（转换为渲染单位）
    kerning->xShift = kerning->xShift / sft->font->unitsPerEm * sft->xScale;
    kerning->yShift = kerning->yShift / sft->font->unitsPerEm * sft->yScale;

    return 0;
}

/* 渲染字形到图像。
 * 参数：sft - 渲染配置，glyph - 字形ID，image - 输出图像结构体
 * 返回：成功返回0，失败返回-1 */
int
sft_render(const SFT *sft, SFT_Glyph glyph, SFT_Image image)
{
    uint_fast32_t outline;  // 字形轮廓偏移量
    double transform[6];    // 仿射变换矩阵（2x3）
    int bbox[4];            // 字形边界框（渲染坐标）
    Outline outl;           // 字形轮廓结构体

    // 获取字形轮廓偏移量
    if (outline_offset(sft->font, glyph, &outline) < 0)
        return -1;
    if (!outline)
        return 0; // 无轮廓数据（空白字形）
    // 获取字形边界框
    if (glyph_bbox(sft, outline, bbox) < 0)
        return -1;
    /* 构建仿射变换矩阵：将字形边界框的最小角对齐到图像(0,0)点 */
    transform[0] = sft->xScale / sft->font->unitsPerEm; // X轴缩放因子
    transform[1] = 0.0;                                 // X轴倾斜因子
    transform[2] = 0.0;                                 // Y轴倾斜因子
    transform[4] = sft->xOffset - bbox[0];              // X轴平移（抵消边界框左偏移）
    // 根据Y轴方向标志设置Y轴缩放和平移
    if (sft->flags & SFT_DOWNWARD_Y) {
        transform[3] = -sft->yScale / sft->font->unitsPerEm; // Y轴反向缩放（向下为正）
        transform[5] = bbox[3] - sft->yOffset;              // Y轴平移
    } else {
        transform[3] = +sft->yScale / sft->font->unitsPerEm; // Y轴正向缩放（向上为正）
        transform[5] = sft->yOffset - bbox[1];              // Y轴平移
    }
    
    memset(&outl, 0, sizeof outl); // 初始化轮廓结构体
    if (init_outline(&outl) < 0)
        goto failure; // 初始化失败，跳转到错误处理

    // 解码字形轮廓
    if (decode_outline(sft->font, outline, 0, &outl) < 0)
        goto failure;
    // 渲染轮廓到图像
    if (render_outline(&outl, transform, image) < 0)
        goto failure;

    free_outline(&outl); // 释放轮廓资源
    return 0;

failure:
    free_outline(&outl); // 错误处理：释放轮廓资源
    return -1;
}

/* 这是 SIZE_MAX+1 的平方根，当 s1*s2 <= SIZE_MAX 时，
 * 要求 s1 < MUL_NO_OVERFLOW 且 s2 < MUL_NO_OVERFLOW */
#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))

/* OpenBSD的reallocarray()标准库函数。
 * 是realloc()的包装器，接收两个尺寸参数（类似calloc()）。
 * 用于避免常见的整数溢出错误。 */
static void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
    // 检查是否会发生整数溢出
    if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
        nmemb > 0 && SIZE_MAX / nmemb < size) {
        errno = ENOMEM; // 设置内存不足错误码
        return NULL;
    }
    return realloc(optr, size * nmemb); // 调用realloc分配内存
}

/* TODO：或许应该用long代替int。 */
// 快速向下取整（比标准库floor函数更快）
static inline int
fast_floor(double x)
{
    int i = (int) x; // 强制类型转换（截断小数部分）
    return i - (i > x); // 如果原数为负数（如-1.2），i=-1 > x，需减1得到-2
}

// 快速向上取整（比标准库ceil函数更快）
static inline int
fast_ceil(double x)
{
    int i = (int) x; // 强制类型转换（截断小数部分）
    return i + (i < x); // 如果原数为正数（如1.2），i=1 < x，需加1得到2
}

#if defined(_WIN32)

/* Windows平台：将字体文件映射到内存。
 * 参数：font - 字体结构体，filename - 文件路径
 * 返回：成功返回0，失败返回-1 */
static int
map_file(SFT_Font *font, const char *filename)
{
    HANDLE file;         // 文件句柄
    DWORD high, low;     // 文件大小（高位、低位）

    font->mapping = NULL; // 初始化文件映射句柄
    font->memory  = NULL; // 初始化内存指针

    // 打开文件（只读模式）
    file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (file == INVALID_HANDLE_VALUE) {
        return -1;
    }

    // 获取文件大小
    low = GetFileSize(file, &high);
    if (low == INVALID_FILE_SIZE) {
        CloseHandle(file); // 获取大小失败，关闭文件
        return -1;
    }

    // 计算文件总大小（64位转32位，假设文件不超过4GB）
    font->size = (size_t)high << (8 * sizeof(DWORD)) | low;

    // 创建文件映射对象
    font->mapping = CreateFileMapping(file, NULL, PAGE_READONLY, high, low, NULL);
    if (!font->mapping) {
        CloseHandle(file); // 创建映射失败，关闭文件
        return -1;
    }

    CloseHandle(file); // 文件映射后可关闭文件句柄

    // 将文件映射到进程地址空间
    font->memory = MapViewOfFile(font->mapping, FILE_MAP_READ, 0, 0, 0);
    if (!font->memory) {
        CloseHandle(font->mapping); // 映射失败，关闭映射对象
        font->mapping = NULL;
        return -1;
    }

    return 0;
}

/* Windows平台：解除文件内存映射。
 * 参数：font - 字体结构体 */
static void
unmap_file(SFT_Font *font)
{
    if (font->memory) {
        UnmapViewOfFile(font->memory); // 解除内存映射
        font->memory = NULL;
    }
    if (font->mapping) {
        CloseHandle(font->mapping); // 关闭文件映射对象
        font->mapping = NULL;
    }
}

#else

/* Unix-like平台：将字体文件映射到内存。
 * 参数：font - 字体结构体，filename - 文件路径
 * 返回：成功返回0，失败返回-1 */
static int
map_file(SFT_Font *font, const char *filename)
{
    struct stat info; // 文件状态结构体
    int fd;           // 文件描述符
    font->memory = MAP_FAILED; // 初始化内存映射指针（失败标记）
    font->size   = 0;          // 初始化文件大小
    font->source = SrcMapping; // 设置数据源类型为内存映射

    // 打开文件（只读模式，二进制模式）
    if ((fd = open(filename, O_RDONLY)) < 0) {
        return -1;
    }
    // 获取文件状态（包含文件大小）
    if (fstat(fd, &info) < 0) {
        close(fd); // 获取状态失败，关闭文件
        return -1;
    }
    /* FIXME：可能需要对info.st_size进行基本验证（例如是否为负数） */
    // 将文件映射到内存（私有只读模式）
    font->memory = mmap(NULL, (size_t) info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    font->size   = (uint_fast32_t) info.st_size; // 保存文件大小
    close(fd); // 映射后可关闭文件描述符

    // 返回映射结果（MAP_FAILED表示失败）
    return font->memory == MAP_FAILED ? -1 : 0;
}

/* Unix-like平台：解除文件内存映射。
 * 参数：font - 字体结构体 */
static void
unmap_file(SFT_Font *font)
{
    assert(font->memory != MAP_FAILED); // 断言映射有效
    // 解除内存映射
    munmap((void *) font->memory, font->size);
}

#endif

/* 初始化字体元信息（解析head和hhea表）。
 * 参数：font - 字体结构体
 * 返回：成功返回0，失败返回-1 */
static int
init_font(SFT_Font *font)
{
    uint_fast32_t scalerType, head, hhea; // 字体魔术数、head表偏移、hhea表偏移

    // 检查文件头部是否足够（至少12字节）
    if (!is_safe_offset(font, 0, 12))
        return -1;
    // 读取字体魔术数（验证文件格式）
    scalerType = getu32(font, 0);
    if (scalerType != FILE_MAGIC_ONE && scalerType != FILE_MAGIC_TWO)
        return -1; // 不支持的字体格式

    // 查找head表（字体头部信息表）
    if (gettable(font, "head", &head) < 0)
        return -1;
    // 检查head表长度（至少54字节）
    if (!is_safe_offset(font, head, 54))
        return -1;
    // 读取每Em单位数（head表偏移18处）和loca表格式（偏移50处）
    font->unitsPerEm = getu16(font, head + 18);
    font->locaFormat = geti16(font, head + 50);
    
    // 查找hhea表（水平度量表头）
    if (gettable(font, "hhea", &hhea) < 0)
        return -1;
    // 检查hhea表长度（至少36字节）
    if (!is_safe_offset(font, hhea, 36))
        return -1;
    // 读取长水平度量数量（hhea表偏移34处）
    font->numLongHmtx = getu16(font, hhea + 34);

    return 0;
}

/* 计算两点的中点。
 * 参数：a - 第一个点，b - 第二个点
 * 返回：中点坐标 */
static Point
midpoint(Point a, Point b)
{
    return (Point) {
        0.5 * (a.x + b.x), // X坐标：(a.x + b.x)/2
        0.5 * (a.y + b.y)  // Y坐标：(a.y + b.y)/2
    };
}

/* 对一组点应用仿射线性变换矩阵。
 * 参数：numPts - 点的数量，points - 点数组，trf[6] - 2x3仿射变换矩阵
 * 变换公式：x' = x*trf[0] + y*trf[2] + trf[4]
 *          y' = x*trf[1] + y*trf[3] + trf[5] */
static void
transform_points(unsigned int numPts, Point *points, double trf[6])
{
    Point pt; // 临时存储原始点坐标
    unsigned int i;
    for (i = 0; i < numPts; ++i) {
        pt = points[i]; // 保存原始坐标
        // 应用变换矩阵计算新坐标
        points[i] = (Point) {
            pt.x * trf[0] + pt.y * trf[2] + trf[4],
            pt.x * trf[1] + pt.y * trf[3] + trf[5]
        };
    }
}

/* 将点裁剪到指定矩形区域（0<=x<width，0<=y<height）。
 * 参数：numPts - 点的数量，points - 点数组，width - 矩形宽度，height - 矩形高度 */
static void
clip_points(unsigned int numPts, Point *points, int width, int height)
{
    Point pt; // 临时存储原始点坐标
    unsigned int i;

    for (i = 0; i < numPts; ++i) {
        pt = points[i]; // 保存原始坐标

        // X坐标裁剪：小于0设为0，大于等于width设为width的前一个可表示值
        if (pt.x < 0.0) {
            points[i].x = 0.0;
        }
        if (pt.x >= width) {
            points[i].x = nextafter(width, 0.0); // 比width小的最大双精度值
        }
        // Y坐标裁剪：小于0设为0，大于等于height设为height的前一个可表示值
        if (pt.y < 0.0) {
            points[i].y = 0.0;
        }
        if (pt.y >= height) {
            points[i].y = nextafter(height, 0.0);
        }
    }
}

/* 初始化轮廓结构体（分配初始内存）。
 * 参数：outl - 轮廓结构体指针
 * 返回：成功返回0，失败返回-1 */
static int
init_outline(Outline *outl)
{
    /* TODO：可以使用更小的初始分配大小 */
    outl->numPoints = 0;          // 初始点数量为0
    outl->capPoints = 64;         // 点数组初始容量64
    // 分配点数组内存
    if (!(outl->points = malloc(outl->capPoints * sizeof *outl->points)))
        return -1;
    outl->numCurves = 0;          // 初始曲线数量为0
    outl->capCurves = 64;         // 曲线数组初始容量64
    // 分配曲线数组内存
    if (!(outl->curves = malloc(outl->capCurves * sizeof *outl->curves)))
        return -1;
    outl->numLines = 0;           // 初始线段数量为0
    outl->capLines = 64;          // 线段数组初始容量64
    // 分配线段数组内存
    if (!(outl->lines = malloc(outl->capLines * sizeof *outl->lines)))
        return -1;
    return 0;
}

/* 释放轮廓结构体内存。
 * 参数：outl - 轮廓结构体指针 */
static void
free_outline(Outline *outl)
{
    free(outl->points); // 释放点数组
    free(outl->curves); // 释放曲线数组
    free(outl->lines);  // 释放线段数组
}

/* 扩展点数组容量（2倍扩容）。
 * 参数：outl - 轮廓结构体指针
 * 返回：成功返回0，失败返回-1 */
static int
grow_points(Outline *outl)
{
    void *mem; // 新内存指针
    uint_fast16_t cap; // 新容量
    assert(outl->capPoints); // 断言当前容量非0
    // 检查扩容后是否溢出（uint_least16_t最大为65535）
    if (outl->capPoints > UINT16_MAX / 2)
        return -1;
    cap = (uint_fast16_t) (2U * outl->capPoints); // 新容量为当前2倍
    // 重分配内存（保持原有数据）
    if (!(mem = reallocarray(outl->points, cap, sizeof *outl->points)))
        return -1;
    // 更新容量和指针
    outl->capPoints = (uint_least16_t) cap;
    outl->points    = mem;
    return 0;
}

/* 扩展曲线数组容量（2倍扩容）。
 * 参数：outl - 轮廓结构体指针
 * 返回：成功返回0，失败返回-1 */
static int
grow_curves(Outline *outl)
{
    void *mem; // 新内存指针
    uint_fast16_t cap; // 新容量
    assert(outl->capCurves); // 断言当前容量非0
    // 检查扩容后是否溢出
    if (outl->capCurves > UINT16_MAX / 2)
        return -1;
    cap = (uint_fast16_t) (2U * outl->capCurves); // 新容量为当前2倍
    // 重分配内存
    if (!(mem = reallocarray(outl->curves, cap, sizeof *outl->curves)))
        return -1;
    // 更新容量和指针
    outl->capCurves = (uint_least16_t) cap;
    outl->curves    = mem;
    return 0;
}

/* 扩展线段数组容量（2倍扩容）。
 * 参数：outl - 轮廓结构体指针
 * 返回：成功返回0，失败返回-1 */
static int
grow_lines(Outline *outl)
{
    void *mem; // 新内存指针
    uint_fast16_t cap; // 新容量
    assert(outl->capLines); // 断言当前容量非0
    // 检查扩容后是否溢出
    if (outl->capLines > UINT16_MAX / 2)
        return -1;
    cap = (uint_fast16_t) (2U * outl->capLines); // 新容量为当前2倍
    // 重分配内存
    if (!(mem = reallocarray(outl->lines, cap, sizeof *outl->lines)))
        return -1;
    // 更新容量和指针
    outl->capLines = (uint_least16_t) cap;
    outl->lines    = mem;
    return 0;
}

/* 检查偏移量是否安全（避免内存越界）。
 * 参数：font - 字体结构体，offset - 偏移量，margin - 所需字节数
 * 返回：安全返回1，不安全返回0 */
static inline int
is_safe_offset(SFT_Font *font, uint_fast32_t offset, uint_fast32_t margin)
{
    if (offset > font->size) return 0; // 偏移量超过文件大小
    if (font->size - offset < margin) return 0; // 剩余空间不足
    return 1;
}

/* 类似bsearch()，但如果未找到键则返回下一个更大的元素。
 * 参数：key - 查找键，base - 数据起始地址，nmemb - 元素数量，size - 元素大小，compar - 比较函数
 * 返回：找到的元素指针或下一个更大元素指针，无则返回NULL */
static void *
csearch(const void *key, const void *base,
	size_t nmemb, size_t size,
	int (*compar)(const void *, const void *))
{
	const uint8_t *bytes = base; // 数据字节指针
	const uint8_t *sample;       // 当前样本元素指针
	size_t low = 0, high = nmemb - 1, mid; // 二分查找边界和中间索引
	if (!nmemb) return NULL; // 无元素，返回NULL
	// 二分查找循环
	while (low != high) {
		mid = low + (high - low) / 2; // 计算中间索引（避免溢出）
		sample = bytes + mid * size; // 获取中间元素地址
		if (compar(key, sample) > 0) {
			low = mid + 1; // 键大于中间元素，查找右半部分
		} else {
			high = mid; // 键小于等于中间元素，查找左半部分
		}
	}
	// 返回找到的元素或下一个更大元素
	return (uint8_t *) bytes + low * size;
}

/* 用于[bc]search()的16位无符号整数比较函数。
 * 参数：a - 第一个元素指针，b - 第二个元素指针
 * 返回：a < b返回负数，a == b返回0，a > b返回正数 */
static int
cmpu16(const void *a, const void *b)
{
	return memcmp(a, b, 2); // 直接比较2字节内存
}

/* 用于[bc]search()的32位无符号整数比较函数。
 * 参数：a - 第一个元素指针，b - 第二个元素指针
 * 返回：a < b返回负数，a == b返回0，a > b返回正数 */
static int
cmpu32(const void *a, const void *b)
{
	return memcmp(a, b, 4); // 直接比较4字节内存
}

/* 从字体内存读取8位无符号整数。
 * 参数：font - 字体结构体，offset - 偏移量
 * 返回：8位无符号整数 */
static inline uint_least8_t
getu8(SFT_Font *font, uint_fast32_t offset)
{
	assert(offset + 1 <= font->size); // 断言偏移量安全
	return *(font->memory + offset); // 直接取字节值
}

/* 从字体内存读取8位有符号整数。
 * 参数：font - 字体结构体，offset - 偏移量
 * 返回：8位有符号整数 */
static inline int_least8_t
geti8(SFT_Font *font, uint_fast32_t offset)
{
	return (int_least8_t) getu8(font, offset); // 转换为有符号类型
}

/* 从字体内存读取16位无符号整数（大端字节序）。
 * 参数：font - 字体结构体，offset - 偏移量
 * 返回：16位无符号整数 */
static inline uint_least16_t
getu16(SFT_Font *font, uint_fast32_t offset)
{
	assert(offset + 2 <= font->size); // 断言偏移量安全
	const uint8_t *base = font->memory + offset; // 数据起始地址
	uint_least16_t b1 = base[0], b0 = base[1]; // 高8位、低8位
	return (uint_least16_t) (b1 << 8 | b0); // 组合为16位整数（大端）
}

/* 从字体内存读取16位有符号整数（大端字节序）。
 * 参数：font - 字体结构体，offset - 偏移量
 * 返回：16位有符号整数 */
static inline int16_t
geti16(SFT_Font *font, uint_fast32_t offset)
{
	return (int_least16_t) getu16(font, offset); // 转换为有符号类型
}

/* 从字体内存读取32位无符号整数（大端字节序）。
 * 参数：font - 字体结构体，offset - 偏移量
 * 返回：32位无符号整数 */
static inline uint32_t
getu32(SFT_Font *font, uint_fast32_t offset)
{
	assert(offset + 4 <= font->size); // 断言偏移量安全
	const uint8_t *base = font->memory + offset; // 数据起始地址
	// 高24位、中16位、中8位、低8位（大端）
	uint_least32_t b3 = base[0], b2 = base[1], b1 = base[2], b0 = base[3]; 
	return (uint_least32_t) (b3 << 24 | b2 << 16 | b1 << 8 | b0); // 组合为32位整数
}

/* 根据4字节标签查找TTF表的偏移量。
 * 参数：font - 字体结构体，tag[4] - 表标签（如"head"），offset - 输出表偏移量
 * 返回：成功返回0，失败返回-1 */
static int
gettable(SFT_Font *font, char tag[4], uint_fast32_t *offset)
{
	void *match; // 查找结果
	unsigned int numTables; // 表数量
	/* 无需检查前12字节的边界 - init_font()已检查 */
	numTables = getu16(font, 4); // 读取表数量（字体文件偏移4处）
	// 检查表目录是否足够（每个表项16字节）
	if (!is_safe_offset(font, 12, (uint_fast32_t) numTables * 16))
		return -1;
	// 二分查找表标签（表目录从偏移12开始，每个表项16字节，前4字节为标签）
	if (!(match = bsearch(tag, font->memory + 12, numTables, 16, cmpu32)))
		return -1; // 未找到表
	// 读取表的偏移量（表项偏移8处，4字节）
	*offset = getu32(font, (uint_fast32_t) ((uint8_t *) match - font->memory + 8));
	return 0;
}

/* 解析格式4的cmap表（用于Unicode BMP，支持不连续编码范围）。
 * 参数：font - 字体结构体，table - cmap子表偏移，charCode - 编码点，glyph - 输出字形ID
 * 返回：成功返回0，失败返回-1 */
static int
cmap_fmt4(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph)
{
	const uint8_t *segPtr; // 找到的段指针
	uint_fast32_t segIdxX2; // 段索引×2（因为段结束码是16位）
	uint_fast32_t endCodes, startCodes, idDeltas, idRangeOffsets, idOffset; // 段数组偏移
	uint_fast16_t segCountX2, idRangeOffset, startCode, shortCode, idDelta, id; // 段参数
	uint8_t key[2] = { (uint8_t) (charCode >> 8), (uint8_t) charCode }; // 查找键（16位编码点）
	/* 格式4的cmap表仅支持Unicode BMP（0x0000-0xFFFF） */
	if (charCode > 0xFFFF) {
		*glyph = 0; // 超出范围返回0（空白字形）
		return 0;
	}
	shortCode = (uint_fast16_t) charCode; // 编码点转换为16位
	// 检查cmap子表头部（至少8字节）
	if (!is_safe_offset(font, table, 8))
		return -1;
	segCountX2 = getu16(font, table); // 段数量×2（每个段结束码16位）
	if ((segCountX2 & 1) || !segCountX2)
		return -1; // 段数量×2必须为偶数且非0
	/* 计算各段数组的偏移量 */
	endCodes       = table + 8;          // 段结束码数组
	startCodes     = endCodes + segCountX2 + 2; // 段起始码数组（结束码数组后加2字节填充）
	idDeltas       = startCodes + segCountX2; // 字形ID增量数组
	idRangeOffsets = idDeltas + segCountX2; // 字形ID范围偏移数组
	// 检查数组是否足够长
	if (!is_safe_offset(font, idRangeOffsets, segCountX2))
		return -1;
	/* 通过二分查找段结束码数组，找到包含当前编码点的段 */
	segPtr = csearch(key, font->memory + endCodes, segCountX2 / 2, 2, cmpu16);
	segIdxX2 = (uint_fast32_t) (segPtr - (font->memory + endCodes)); // 段索引×2
	/* 读取段信息并短路判断 */
	if ((startCode = getu16(font, startCodes + segIdxX2)) > shortCode)
		return 0; // 编码点小于段起始码，返回0
	idDelta = getu16(font, idDeltas + segIdxX2); // 段的字形ID增量
	if (!(idRangeOffset = getu16(font, idRangeOffsets + segIdxX2))) {
		/* 无范围偏移：字形ID = (编码点 + 增量) & 0xFFFF（允许溢出） */
		*glyph = (shortCode + idDelta) & 0xFFFF;
		return 0;
	}
	/* 有范围偏移：计算字形ID数组偏移 */
	idOffset = idRangeOffsets + segIdxX2 + idRangeOffset + 2U * (unsigned int) (shortCode - startCode);
	// 检查偏移量安全
	if (!is_safe_offset(font, idOffset, 2))
		return -1;
	id = getu16(font, idOffset); // 读取字形ID
	/* 字形ID = (读取的ID + 增量) & 0xFFFF（ID为0时返回0） */
	*glyph = id ? (id + idDelta) & 0xFFFF : 0;
	return 0;
}

/* 解析格式6的cmap表（用于连续编码范围，查找效率高）。
 * 参数：font - 字体结构体，table - cmap子表偏移，charCode - 编码点，glyph - 输出字形ID
 * 返回：成功返回0，失败返回-1 */
static int
cmap_fmt6(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph)
{
	unsigned int firstCode, entryCount; // 起始编码点、条目数量
	/* 格式6的cmap表仅支持Unicode BMP（0x0000-0xFFFF） */
	if (charCode > 0xFFFF) {
		*glyph = 0;
		return 0;
	}
	// 检查cmap子表头部（至少4字节）
	if (!is_safe_offset(font, table, 4))
		return -1;
	firstCode  = getu16(font, table);     // 起始编码点
	entryCount = getu16(font, table + 2); // 条目数量（编码点数量）
	// 检查条目数组是否足够长（每个条目2字节）
	if (!is_safe_offset(font, table, 4 + 2 * entryCount))
		return -1;
	// 编码点小于起始码，返回0
	if (charCode < firstCode)
		return -1;
	charCode -= firstCode; // 计算编码点在条目数组中的索引
	// 编码点超出范围，返回0
	if (!(charCode < entryCount))
		return -1;
	// 读取对应的字形ID（条目数组偏移4 + 索引×2）
	*glyph = getu16(font, table + 4 + 2 * charCode);
	return 0;
}

/* 解析格式12或13的cmap表（支持非BMP编码点，范围更大）。
 * 参数：font - 字体结构体，table - cmap子表偏移，charCode - 编码点，glyph - 输出字形ID，which - 12=格式12，其他=格式13
 * 返回：成功返回0，失败返回-1 */
static int
cmap_fmt12_13(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph, int which)
{
	uint32_t len, numEntries; // 子表长度、条目数量
	uint_fast32_t i;          // 循环索引

	*glyph = 0; // 初始化字形ID为0

    /* 检查子表头部是否完整（至少16字节） */
	if (!is_safe_offset(font, table, 16))
		return -1;

	len = getu32(font, table + 4); // 读取子表长度

	/* 最小头部长度为16字节 */
	if (len < 16)
		return -1;

	// 检查子表是否足够长
	if (!is_safe_offset(font, table, len))
		return -1;

	numEntries = getu32(font, table + 12); // 读取条目数量

	// 遍历所有条目（每个条目12字节：起始码4字节、结束码4字节、字形ID/偏移4字节）
	for (i = 0; i < numEntries; ++i) {
		uint32_t firstCode, lastCode, glyphOffset;
		firstCode = getu32(font, table + (i * 12) + 16); // 条目起始码
		lastCode = getu32(font, table + (i * 12) + 16 + 4); // 条目结束码
		// 编码点不在当前条目范围内，跳过
		if (charCode < firstCode || charCode > lastCode)
			continue;
		glyphOffset = getu32(font, table + (i * 12) + 16 + 8); // 字形ID/偏移
		// 格式12：字形ID = 编码点 - 起始码 + 偏移；格式13：字形ID = 偏移
		if (which == 12)
			*glyph = (charCode-firstCode) + glyphOffset;
		else
			*glyph = glyphOffset;
		return 0;
	}

	return 0;
}

/* 将Unicode编码点转换为字形ID（自动选择合适的cmap表）。
 * 参数：font - 字体结构体，charCode - Unicode编码点，glyph - 输出字形ID
 * 返回：成功返回0，失败返回-1 */
static int
glyph_id(SFT_Font *font, SFT_UChar charCode, SFT_Glyph *glyph)
{
	uint_fast32_t cmap, entry, table; // cmap表偏移、条目偏移、子表偏移
	unsigned int idx, numEntries;     // 条目索引、条目数量
	int type;                         // 编码类型（平台ID×0100 + 编码ID）
	uint16_t format;                  // cmap子表格式
	
	*glyph = 0; // 初始化字形ID为0

	// 查找cmap表（字符映射表）
	if (gettable(font, "cmap", &cmap) < 0)
		return -1;

	// 检查cmap表头部（至少4字节）
	if (!is_safe_offset(font, cmap, 4))
		return -1;
	numEntries = getu16(font, cmap + 2); // 读取cmap条目数量

	// 检查cmap条目目录是否足够（每个条目8字节）
	if (!is_safe_offset(font, cmap, 4 + numEntries * 8))
		return -1;

	/* 首先查找支持全字符集/非BMP的cmap表（格式12） */
	for (idx = 0; idx < numEntries; ++idx) {
		entry = cmap + 4 + idx * 8; // 当前条目偏移
		// 计算编码类型（平台ID×0100 + 编码ID）
		type = getu16(font, entry) * 0100 + getu16(font, entry + 2);
		/* 全Unicode映射（平台ID=0，编码ID=4；或平台ID=3，编码ID=12） */
		if (type == 0004 || type == 0312) {
			table = cmap + getu32(font, entry + 4); // 子表偏移
			// 检查子表头部（至少8字节）
			if (!is_safe_offset(font, table, 8))
				return -1;
			// 根据子表格式解析
			format = getu16(font, table);
			switch (format) {
			case 12:
				return cmap_fmt12_13(font, table, charCode, glyph, 12);
			default:
				return -1; // 不支持的子表格式
			}
		}
	}

	/* 如果未找到全字符集cmap表，查找BMP映射表 */
	for (idx = 0; idx < numEntries; ++idx) {
		entry = cmap + 4 + idx * 8; // 当前条目偏移
		// 计算编码类型
		type = getu16(font, entry) * 0100 + getu16(font, entry + 2);
		/* Unicode BMP映射（平台ID=0，编码ID=3；或平台ID=3，编码ID=1） */
		if (type == 0003 || type == 0301) {
			table = cmap + getu32(font, entry + 4); // 子表偏移
			// 检查子表头部（至少6字节）
			if (!is_safe_offset(font, table, 6))
				return -1;
			// 根据子表格式解析
			switch (getu16(font, table)) {
			case 4:
				return cmap_fmt4(font, table + 6, charCode, glyph); // 格式4
			case 6:
				return cmap_fmt6(font, table + 6, charCode, glyph); // 格式6
			default:
				return -1; // 不支持的子表格式
			}
		}
	}

	return -1; // 未找到合适的cmap表
}

/* 获取字形的水平度量（前进宽度和左bearing）。
 * 参数：font - 字体结构体，glyph - 字形ID，advanceWidth - 输出前进宽度，leftSideBearing - 输出左bearing
 * 返回：成功返回0，失败返回-1 */
static int
hor_metrics(SFT_Font *font, SFT_Glyph glyph, int *advanceWidth, int *leftSideBearing)
{
	uint_fast32_t hmtx, offset, boundary; // hmtx表偏移、当前偏移、长/短度量边界
	// 查找hmtx表（水平度量表）
	if (gettable(font, "hmtx", &hmtx) < 0)
		return -1;
	// 字形ID在长度量范围内（每个长度量4字节：前进宽度2字节 + 左bearing2字节）
	if (glyph < font->numLongHmtx) {
		offset = hmtx + 4 * glyph; // 计算当前字形的度量偏移
		// 检查偏移量安全
		if (!is_safe_offset(font, offset, 4))
			return -1;
		// 读取前进宽度（无符号16位）和左bearing（有符号16位）
		*advanceWidth = getu16(font, offset);
		*leftSideBearing = geti16(font, offset + 2);
		return 0;
	} else {
		// 字形ID在短度量范围内（仅存储左bearing，前进宽度复用最后一个长度量）
		boundary = hmtx + 4U * (uint_fast32_t) font->numLongHmtx; // 长/短度量边界
		if (boundary < 4)
			return -1; // 边界无效
		
		offset = boundary - 4; // 最后一个长度量的偏移
		// 读取复用的前进宽度
		if (!is_safe_offset(font, offset, 4))
			return -1;
		*advanceWidth = getu16(font, offset);
		
		// 计算当前字形的左bearing偏移（短度量每个条目2字节）
		offset = boundary + 2 * (glyph - font->numLongHmtx);
		// 读取左bearing
		if (!is_safe_offset(font, offset, 2))
			return -1;
		*leftSideBearing = geti16(font, offset);
		return 0;
	}
}

/* 获取字形的边界框（转换为渲染坐标）。
 * 参数：sft - 渲染配置，outline - 字形轮廓偏移量，box[4] - 输出边界框（left, top, right, bottom）
 * 返回：成功返回0，失败返回-1 */
static int
glyph_bbox(const SFT *sft, uint_fast32_t outline, int box[4])
{
	double xScale, yScale; // X/Y轴缩放因子（设计单位转渲染单位）
	/* 从glyf表读取字形边界框（原始设计单位） */
	if (!is_safe_offset(sft->font, outline, 10))
		return -1;
	box[0] = geti16(sft->font, outline + 2); // 左边界（xMin）
	box[1] = geti16(sft->font, outline + 4); // 上边界（yMin）
	box[2] = geti16(sft->font, outline + 6); // 右边界（xMax）
	box[3] = geti16(sft->font, outline + 8); // 下边界（yMax）
	// 边界框无效（右<=左或下<=上）
	if (box[2] <= box[0] || box[3] <= box[1])
		return -1;
	/* 将边界框转换为渲染坐标 */
	xScale = sft->xScale / sft->font->unitsPerEm; // X轴缩放因子
	yScale = sft->yScale / sft->font->unitsPerEm; // Y轴缩放因子
	// 应用缩放和偏移，取整（left和top向下取整，right和bottom向上取整）
	box[0] = (int) floor(box[0] * xScale + sft->xOffset);
	box[1] = (int) floor(box[1] * yScale + sft->yOffset);
	box[2] = (int) ceil (box[2] * xScale + sft->xOffset);
		box[3] = (int) ceil (box[3] * yScale + sft->yOffset);
	return 0;
}

/* 获取字形轮廓在glyf表中的偏移量。
 * 参数：font - 字体结构体，glyph - 字形ID，offset - 输出轮廓偏移量（相对于glyf表）
 * 返回：成功返回0，失败返回-1 */
static int
outline_offset(SFT_Font *font, SFT_Glyph glyph, uint_fast32_t *offset)
{
	uint_fast32_t loca, glyf; // loca表偏移、glyf表偏移
	uint_fast32_t base, this, next; // loca表中当前字形的偏移基数、当前偏移、下一个偏移

	// 查找loca表（字形轮廓偏移表）和glyf表（字形轮廓数据）
	if (gettable(font, "loca", &loca) < 0)
		return -1;
	if (gettable(font, "glyf", &glyf) < 0)
		return -1;

	// 根据loca表格式读取当前字形和下一个字形的偏移
	if (font->locaFormat == 0) {
		// 格式0：每个偏移16位（需×2转换为glyf表中的字节偏移）
		base = loca + 2 * glyph; // 当前字形在loca表中的偏移基数

		// 检查偏移是否安全（需读取2个16位值，共4字节）
		if (!is_safe_offset(font, base, 4))
			return -1;
		
		this = 2U * (uint_fast32_t) getu16(font, base);     // 当前字形的glyf表偏移
		next = 2U * (uint_fast32_t) getu16(font, base + 2); // 下一个字形的glyf表偏移
	} else {
		// 格式1：每个偏移32位（直接作为glyf表中的字节偏移）
		base = loca + 4 * glyph; // 当前字形在loca表中的偏移基数

		// 检查偏移是否安全（需读取2个32位值，共8字节）
		if (!is_safe_offset(font, base, 8))
			return -1;

		this = getu32(font, base);     // 当前字形的glyf表偏移
		next = getu32(font, base + 4); // 下一个字形的glyf表偏移
	}

	// 若当前偏移与下一个偏移相等，说明无轮廓数据（偏移设为0）；否则为glyf表偏移+当前偏移
	*offset = this == next ? 0 : glyf + this;
	return 0;
}

/* 解析简单字形的点标志（处理重复标志压缩）。
 * 参数：font - 字体结构体，offset - 输入输出偏移量（解析后指向点坐标数据），numPts - 点数量，flags - 输出点标志数组
 * 返回：成功返回0，失败返回-1 */
static int
simple_flags(SFT_Font *font, uint_fast32_t *offset, uint_fast16_t numPts, uint8_t *flags)
{
	uint_fast32_t off = *offset; // 临时偏移量（避免直接修改输入）
	uint_fast16_t i;             // 循环索引
	uint8_t value = 0, repeat = 0; // 当前标志值、重复次数

	for (i = 0; i < numPts; ++i) {
		if (repeat) {
			// 有重复次数，直接复用上次的标志值
			--repeat;
		} else {
			// 读取新的标志值
			if (!is_safe_offset(font, off, 1))
				return -1;
			value = getu8(font, off++);
			// 检查是否有重复标志
			if (value & REPEAT_FLAG) {
				// 读取重复次数（下一个字节）
				if (!is_safe_offset(font, off, 1))
					return -1;
				repeat = getu8(font, off++);
			}
		}
		flags[i] = value; // 保存标志值
	}
	*offset = off; // 更新偏移量（指向点坐标数据）
	return 0;
}

/* 解析简单字形的点坐标（处理可变长度压缩存储）。
 * 参数：font - 字体结构体，offset - 点坐标数据偏移量，numPts - 点数量，flags - 点标志数组，points - 输出点坐标数组
 * 返回：成功返回0，失败返回-1 */
static int
simple_points(SFT_Font *font, uint_fast32_t offset, uint_fast16_t numPts, uint8_t *flags, Point *points)
{
	long accum, value, bit; // 累积坐标值、当前变化量、符号位
	uint_fast16_t i;        // 循环索引

	/* 解析X坐标 */
	accum = 0L; // 累积X坐标（相对坐标转绝对坐标）
	for (i = 0; i < numPts; ++i) {
		if (flags[i] & X_CHANGE_IS_SMALL) {
			// X坐标变化量较小（1字节存储）
			if (!is_safe_offset(font, offset, 1))
				return -1;
			value = (long) getu8(font, offset++);
			bit = !!(flags[i] & X_CHANGE_IS_POSITIVE); // 符号位（1=正，0=负）
			// 计算实际变化量（负数用补码转换）
			accum -= (value ^ -bit) + bit;
		} else if (!(flags[i] & X_CHANGE_IS_ZERO)) {
			// X坐标变化量较大（2字节存储，有符号）
			if (!is_safe_offset(font, offset, 2))
				return -1;
			accum += geti16(font, offset);
			offset += 2;
		}
		points[i].x = (double) accum; // 保存X坐标（转换为双精度）
	}

	/* 解析Y坐标 */
	accum = 0L; // 累积Y坐标
	for (i = 0; i < numPts; ++i) {
		if (flags[i] & Y_CHANGE_IS_SMALL) {
			// Y坐标变化量较小（1字节存储）
			if (!is_safe_offset(font, offset, 1))
				return -1;
			value = (long) getu8(font, offset++);
			bit = !!(flags[i] & Y_CHANGE_IS_POSITIVE); // 符号位
			accum -= (value ^ -bit) + bit; // 计算实际变化量
		} else if (!(flags[i] & Y_CHANGE_IS_ZERO)) {
			// Y坐标变化量较大（2字节存储，有符号）
			if (!is_safe_offset(font, offset, 2))
				return -1;
			accum += geti16(font, offset);
			offset += 2;
		}
		points[i].y = (double) accum; // 保存Y坐标
	}

	return 0;
}

/* 解码单个轮廓（将TTF点序列转换为线段和二次贝塞尔曲线）。
 * 参数：flags - 点标志数组，basePoint - 轮廓起始点在全局点数组中的索引，count - 轮廓包含的点数，outl - 输出轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
decode_contour(uint8_t *flags, uint_fast16_t basePoint, uint_fast16_t count, Outline *outl)
{
	uint_fast16_t i; // 循环索引
	uint_least16_t looseEnd, beg, ctrl, center, cur; // 轮廓端点、当前线段起点、控制点、中点、当前点索引
	unsigned int gotCtrl; // 是否已获取控制点（1=是，0=否）

	/* 跳过少于2个点的轮廓（无法构成线段/曲线，无实际面积） */
	if (count < 2) return 0;

	assert(basePoint <= UINT16_MAX - count); // 断言索引不溢出

	/* 处理轮廓的"松散端点"（非曲线点的起始/结束点） */
	if (flags[0] & POINT_IS_ON_CURVE) {
		// 第一个点在曲线上，作为松散端点
		looseEnd = (uint_least16_t) basePoint++;
		++flags; // 标志数组指针后移
		--count; // 点数减1
	} else if (flags[count - 1] & POINT_IS_ON_CURVE) {
		// 最后一个点在曲线上，作为松散端点
		looseEnd = (uint_least16_t) (basePoint + --count);
	} else {
		// 首尾点都不在曲线上，计算首尾点的中点作为松散端点
		if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0)
			return -1;

		looseEnd = outl->numPoints;
		outl->points[outl->numPoints++] = midpoint(
			outl->points[basePoint],
			outl->points[basePoint + count - 1]);
	}

	beg = looseEnd; // 当前线段/曲线的起点
	gotCtrl = 0;    // 初始未获取控制点

	for (i = 0; i < count; ++i) {
		/* cur不会溢出（decode_contour调用前已确保basePoint + count < 0xFFFF） */
		cur = (uint_least16_t) (basePoint + i); // 当前点在全局点数组中的索引
		/* 注：clang静态分析器可能会标记此处为未初始化——这是已知bug，
		 * 即使显式循环初始化flags和points，仍可能误报（memset无此问题）
		 * 参考：http://clang-developers.42468.n3.nabble.com/StaticAnalyzer-False-positive-with-loop-handling-td4053875.html */
		
		if (flags[i] & POINT_IS_ON_CURVE) {
			// 当前点在曲线上
			if (gotCtrl) {
				// 已获取控制点，构成二次贝塞尔曲线
				if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0)
					return -1;
				outl->curves[outl->numCurves++] = (Curve) { beg, cur, ctrl };
			} else {
				// 未获取控制点，构成线段
				if (outl->numLines >= outl->capLines && grow_lines(outl) < 0)
					return -1;
				outl->lines[outl->numLines++] = (Line) { beg, cur };
			}
			beg = cur;      // 更新起点为当前点
			gotCtrl = 0;    // 重置控制点标记
		} else {
			// 当前点是控制点
			if (gotCtrl) {
				// 已存在前一个控制点，需插入中点拆分曲线（TTF轮廓规则）
				center = outl->numPoints;
				if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0)
					return -1;
				// 计算前一个控制点和当前控制点的中点
				outl->points[center] = midpoint(outl->points[ctrl], outl->points[cur]);
				++outl->numPoints;

				// 前半段曲线：起点→中点（以原控制点为控制点）
				if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0)
					return -1;
				outl->curves[outl->numCurves++] = (Curve) { beg, center, ctrl };

				beg = center; // 更新起点为中点
			}
			ctrl = cur;      // 记录当前控制点
			gotCtrl = 1;     // 标记已获取控制点
		}
	}

	/* 处理轮廓的闭合（连接最后一个点和松散端点） */
	if (gotCtrl) {
		// 存在未闭合的曲线，连接到松散端点
		if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0)
			return -1;
		outl->curves[outl->numCurves++] = (Curve) { beg, looseEnd, ctrl };
	} else {
		// 存在未闭合的线段，连接到松散端点
		if (outl->numLines >= outl->capLines && grow_lines(outl) < 0)
			return -1;
		outl->lines[outl->numLines++] = (Line) { beg, looseEnd };
	}

	return 0;
}

/* 解码简单字形轮廓（由多个独立轮廓组成，无嵌套/组合）。
 * 参数：font - 字体结构体，offset - 字形轮廓数据偏移量，numContours - 轮廓数量，outl - 输出轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
simple_outline(SFT_Font *font, uint_fast32_t offset, unsigned int numContours, Outline *outl)
{
	uint_fast16_t *endPts = NULL; // 每个轮廓的结束点索引数组
	uint8_t *flags = NULL;        // 点标志数组
	uint_fast16_t numPts;         // 总点数
	unsigned int i;               // 循环索引

	assert(numContours > 0); // 断言轮廓数量非0

	uint_fast16_t basePoint = outl->numPoints; // 当前字形的点在全局点数组中的起始索引

	// 检查轮廓结束点索引数组是否足够（每个索引2字节，共numContours个）
	if (!is_safe_offset(font, offset, numContours * 2 + 2))
		goto failure;
	// 最后一个轮廓的结束点索引+1即为总点数
	numPts = getu16(font, offset + (numContours - 1) * 2);
	if (numPts >= UINT16_MAX)
		goto failure; // 点数溢出
	numPts++;
	// 检查全局点数组是否能容纳当前字形的点
	if (outl->numPoints > UINT16_MAX - numPts)
		goto failure;

	// 扩展全局点数组容量（确保能容纳当前字形的点）
	while (outl->capPoints < basePoint + numPts) {
		if (grow_points(outl) < 0)
			goto failure;
	}
	
	// 分配轮廓结束点索引数组（栈/堆动态分配）
	STACK_ALLOC(endPts, uint_fast16_t, 16, numContours);
	if (endPts == NULL)
		goto failure;
	// 分配点标志数组（栈/堆动态分配）
	STACK_ALLOC(flags, uint8_t, 128, numPts);
	if (flags == NULL)
		goto failure;

	// 读取每个轮廓的结束点索引
	for (i = 0; i < numContours; ++i) {
		endPts[i] = getu16(font, offset);
		offset += 2;
	}
	/* 验证结束点索引是否递增（恶意输入可能包含递减索引，直接退出） */
	for (i = 0; i < numContours - 1; ++i) {
		if (endPts[i + 1] < endPts[i] + 1)
			goto failure;
	}
	// 跳过字形边界框（2字节填充 + 4字节边界框，共6字节）
	offset += 2U + getu16(font, offset);

	// 解析点标志（处理重复压缩）
	if (simple_flags(font, &offset, numPts, flags) < 0)
		goto failure;
	// 解析点坐标（相对坐标转绝对坐标）
	if (simple_points(font, offset, numPts, flags, outl->points + basePoint) < 0)
		goto failure;
	// 更新全局点数组的实际数量
	outl->numPoints = (uint_least16_t) (outl->numPoints + numPts);

	// 解码每个轮廓（转换为线段/曲线）
	uint_fast16_t beg = 0; // 当前轮廓的起始点在本地点数组中的索引
	for (i = 0; i < numContours; ++i) {
		uint_fast16_t count = endPts[i] - beg + 1; // 当前轮廓的点数
		if (decode_contour(flags + beg, basePoint + beg, count, outl) < 0)
			goto failure;
		beg = endPts[i] + 1; // 更新下一个轮廓的起始索引
	}

	// 释放动态分配的数组
	STACK_FREE(endPts);
	STACK_FREE(flags);
	return 0;

failure:
	// 错误处理：释放动态分配的数组
	STACK_FREE(endPts);
	STACK_FREE(flags);
	return -1;
}

/* 解码复合字形轮廓（由多个子字形组合而成，支持缩放、平移、旋转等变换）。
 * 参数：font - 字体结构体，offset - 复合字形数据偏移量，recDepth - 递归深度，outl - 输出轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
compound_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl)
{
	double local[6]; // 子字形的局部仿射变换矩阵（2x3）
	uint_fast32_t outline; // 子字形的轮廓偏移量
	unsigned int flags, glyph, basePoint; // 复合字形标志、子字形ID、子字形点在全局数组中的起始索引
	/* 防止递归溢出（复合字形嵌套自身，限制最大递归深度为4） */
	if (recDepth >= 4)
		return -1;

	do {
		memset(local, 0, sizeof local); // 初始化变换矩阵为单位矩阵
		// 读取复合字形组件头部（4字节：标志2字节 + 子字形ID2字节）
		if (!is_safe_offset(font, offset, 4))
			return -1;
		flags = getu16(font, offset); // 组件标志
		glyph = getu16(font, offset + 2); // 子字形ID
		offset += 4;

		/* 不支持点匹配模式（stb_truetype也不支持），仅支持实际XY偏移 */
		if (!(flags & ACTUAL_XY_OFFSETS))
			return -1;

		/* 读取子字形的XY偏移量（相对于父字形） */
		if (flags & OFFSETS_ARE_LARGE) {
			// 偏移量为16位有符号整数（2字节/轴）
			if (!is_safe_offset(font, offset, 4))
				return -1;
			local[4] = geti16(font, offset);   // X轴偏移
			local[5] = geti16(font, offset + 2); // Y轴偏移
			offset += 4;
		} else {
			// 偏移量为8位有符号整数（1字节/轴）
			if (!is_safe_offset(font, offset, 2))
				return -1;
			local[4] = geti8(font, offset);    // X轴偏移
			local[5] = geti8(font, offset + 1); // Y轴偏移
			offset += 2;
		}

		/* 读取子字形的缩放/变换参数 */
		if (flags & GOT_A_SINGLE_SCALE) {
			// 单个缩放因子（X/Y轴缩放相同）
			if (!is_safe_offset(font, offset, 2))
				return -1;
			local[0] = geti16(font, offset) / 16384.0; // X轴缩放（16384=2^14，固定分母）
			local[3] = local[0];                       // Y轴缩放（与X轴相同）
			offset += 2;
		} else if (flags & GOT_AN_X_AND_Y_SCALE) {
			// X/Y轴单独缩放
			if (!is_safe_offset(font, offset, 4))
				return -1;
			local[0] = geti16(font, offset + 0) / 16384.0; // X轴缩放
			local[3] = geti16(font, offset + 2) / 16384.0; // Y轴缩放
			offset += 4;
		} else if (flags & GOT_A_SCALE_MATRIX) {
			// 2x2缩放矩阵（支持旋转、倾斜等复杂变换）
			if (!is_safe_offset(font, offset, 8))
				return -1;
			local[0] = geti16(font, offset + 0) / 16384.0; // 矩阵[0][0]
			local[1] = geti16(font, offset + 2) / 16384.0; // 矩阵[0][1]
			local[2] = geti16(font, offset + 4) / 16384.0; // 矩阵[1][0]
			local[3] = geti16(font, offset + 6) / 16384.0; // 矩阵[1][1]
			offset += 8;
		} else {
			// 无缩放：单位矩阵（X/Y轴缩放1.0）
			local[0] = 1.0;
			local[3] = 1.0;
		}

		/* 注：Apple规范建议按L1范数缩放矩阵，stb_truetype按L2范数，FreeType2不缩放
		 * 由于该特性使用极少，此处不额外处理缩放归一化 */

		// 获取子字形的轮廓偏移量
		if (outline_offset(font, glyph, &outline) < 0)
			return -1;
		if (outline) {
			basePoint = outl->numPoints; // 子字形点在全局数组中的起始索引
			// 递归解码子字形轮廓（递归深度+1）
			if (decode_outline(font, outline, recDepth + 1, outl) < 0)
				return -1;
			// 对子字形的所有点应用局部变换矩阵
			transform_points(outl->numPoints - basePoint, outl->points + basePoint, local);
		}
	} while (flags & THERE_ARE_MORE_COMPONENTS); // 存在更多子字形组件，继续循环

	return 0;
}

/* 通用轮廓解码函数（自动区分简单字形和复合字形）。
 * 参数：font - 字体结构体，offset - 字形轮廓数据偏移量，recDepth - 递归深度，outl - 输出轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
decode_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl)
{
	int numContours; // 轮廓数量（正数=简单字形，负数=复合字形，0=无轮廓）
	// 读取轮廓数量（glyf表中字形数据的前2字节）
	if (!is_safe_offset(font, offset, 10))
		return -1;
	numContours = geti16(font, offset);

	if (numContours > 0) {
		/* 正数：简单字形（由numContours个独立轮廓组成） */
		return simple_outline(font, offset + 10, (unsigned int) numContours, outl);
	} else if (numContours < 0) {
		/* 负数：复合字形（绝对值为子字形组件数量） */
		return compound_outline(font, offset + 10, recDepth, outl);
	} else {
		/* 0：无轮廓数据（空白字形） */
		return 0;
	}
}

/* 判断曲线是否足够平坦（可近似为线段，无需进一步细分）。
 * 参数：outl - 轮廓结构体，curve - 待判断的二次贝塞尔曲线
 * 返回：平坦返回1，否则返回0 */
static int
is_flat(Outline *outl, Curve curve)
{
	const double maxArea2 = 2.0; // 最大允许的两倍三角形面积（阈值越小，曲线越平滑）
	Point a = outl->points[curve.beg];   // 曲线起点
	Point b = outl->points[curve.ctrl];  // 曲线控制点
	Point c = outl->points[curve.end];   // 曲线终点
	Point g = { b.x - a.x, b.y - a.y };  // 向量a→b
	Point h = { c.x - a.x, c.y - a.y };  // 向量a→c
	// 计算向量g和h的叉积的绝对值（两倍三角形面积）
	double area2 = fabs(g.x * h.y - h.x * g.y);
	return area2 <= maxArea2; // 面积小于等于阈值则视为平坦
}

/* 细分单条二次贝塞尔曲线为线段（递归细分，直到曲线平坦）。
 * 参数：curve - 待细分的曲线，outl - 输出轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
tesselate_curve(Curve curve, Outline *outl)
{
	/* 测试表明：即使支持最大字体尺寸，栈深度也不超过4，设置10足够应对极端情况 */
#define STACK_SIZE 10
	Curve stack[STACK_SIZE]; // 曲线栈（用于非递归递归细分）
	unsigned int top = 0;    // 栈顶指针
	for (;;) {
		if (is_flat(outl, curve) || top >= STACK_SIZE) {
			// 曲线平坦或栈满，直接转换为线段
			if (outl->numLines >= outl->capLines && grow_lines(outl) < 0)
				return -1;
			outl->lines[outl->numLines++] = (Line) { curve.beg, curve.end };
			if (top == 0) break; // 栈空，细分完成
			curve = stack[--top]; // 弹出栈顶曲线继续细分
		} else {
			// 曲线不平坦，递归细分（德卡斯特里奥算法）
			// 计算中点1：起点和控制点的中点
			uint_least16_t ctrl0 = outl->numPoints;
			if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0)
				return -1;
			outl->points[ctrl0] = midpoint(outl->points[curve.beg], outl->points[curve.ctrl]);
			++outl->numPoints;

			// 计算中点2：控制点和终点的中点
			uint_least16_t ctrl1 = outl->numPoints;
			if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0)
				return -1;
			outl->points[ctrl1] = midpoint(outl->points[curve.ctrl], outl->points[curve.end]);
			++outl->numPoints;

			// 计算中点3：中点1和中点2的中点（细分后两条曲线的公共点）
			uint_least16_t pivot = outl->numPoints;
			if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0)
				return -1;
			outl->points[pivot] = midpoint(outl->points[ctrl0], outl->points[ctrl1]);
			++outl->numPoints;

			// 第一条细分曲线：起点→中点3（控制点为中点1），压入栈
			stack[top++] = (Curve) { curve.beg, pivot, ctrl0 };
			// 第二条细分曲线：中点3→终点（控制点为中点2），当前处理
			curve = (Curve) { pivot, curve.end, ctrl1 };
		}
	}
	return 0;
#undef STACK_SIZE
}

/* 细分轮廓中所有曲线为线段（准备光栅化）。
 * 参数：outl - 轮廓结构体
 * 返回：成功返回0，失败返回-1 */
static int
tesselate_curves(Outline *outl)
{
	unsigned int i;
	// 遍历所有曲线，逐一细分
	for (i = 0; i < outl->numCurves; ++i) {
		if (tesselate_curve(outl->curves[i], outl) < 0)
			return -1;
	}
	return 0;
}

/* 绘制线段到光栅缓冲区（使用自定义2D射线投射算法，计算像素覆盖面积）。
 * 参数：buf - 光栅缓冲区，origin - 线段起点，goal - 线段终点 */
static void
draw_line(Raster buf, Point origin, Point goal)
{
	Point delta;         // 线段向量（终点-起点）
	Point nextCrossing;  // 下一个像素边界交叉点的参数（0~1）
	Point crossingIncr;  // 交叉点参数增量（每跨一个像素的增量）
	double halfDeltaX;   // 线段X向量的一半
	double prevDistance = 0.0, nextDistance; // 上一个/下一个交叉点的参数
	double xAverage, yDifference; // X坐标平均值、Y方向差异（用于计算覆盖面积）
	struct { int x, y; } pixel; // 当前像素坐标
	struct { int x, y; } dir;   // 线段方向（1=正方向，-1=负方向，0=无方向）
	int step, numSteps = 0;     // 当前步骤、总步骤数
	Cell *restrict cptr, cell;  // 当前栅格单元指针、临时存储单元数据

	// 计算线段向量
	delta.x = goal.x - origin.x;
	delta.y = goal.y - origin.y;
	// 计算线段方向（符号函数）
	dir.x = SIGN(delta.x);
	dir.y = SIGN(delta.y);

	if (!dir.y) {
		return; // 水平线段（Y方向无变化），无需处理（光栅化依赖Y方向扫描）
	}
	
	// 计算交叉点参数增量（每跨一个像素，参数增加的值）
	crossingIncr.x = dir.x ? fabs(1.0 / delta.x) : 1.0; // X方向增量（无方向则设为1.0）
	crossingIncr.y = fabs(1.0 / delta.y);               // Y方向增量

	/* 初始化X方向交叉点参数和当前像素X坐标 */
	if (!dir.x) {
		pixel.x = fast_floor(origin.x); // 无X方向，直接取起点X的向下取整
		nextCrossing.x = 100.0;         // 设为大值，避免干扰
	} else {
		if (dir.x > 0) {
			// X正方向：当前像素X为起点X向下取整
			pixel.x = fast_floor(origin.x);
			// 计算下一个X像素边界的交叉点参数
			nextCrossing.x = (origin.x - pixel.x) * crossingIncr.x;
			nextCrossing.x = crossingIncr.x - nextCrossing.x;
			// 计算X方向需要跨越的像素数
			numSteps += fast_ceil(goal.x) - fast_floor(origin.x) - 1;
		} else {
			// X负方向：当前像素X为起点X向上取整-1
			pixel.x = fast_ceil(origin.x) - 1;
			// 计算下一个X像素边界的交叉点参数
			nextCrossing.x = (origin.x - pixel.x) * crossingIncr.x;
			// 计算X方向需要跨越的像素数
			numSteps += fast_ceil(origin.x) - fast_floor(goal.x) - 1;
		}
	}

	/* 初始化Y方向交叉点参数和当前像素Y坐标 */
	if (dir.y > 0) {
		// Y正方向：当前像素Y为起点Y向下取整
		pixel.y = fast_floor(origin.y);
		// 计算下一个Y像素边界的交叉点参数
		nextCrossing.y = (origin.y - pixel.y) * crossingIncr.y;
		nextCrossing.y = crossingIncr.y - nextCrossing.y;
		// 计算Y方向需要跨越的像素数
		numSteps += fast_ceil(goal.y) - fast_floor(origin.y) - 1;
	} else {
		// Y负方向：当前像素Y为起点Y向上取整-1
		pixel.y = fast_ceil(origin.y) - 1;
		// 计算下一个Y像素边界的交叉点参数
		nextCrossing.y = (origin.y - pixel.y) * crossingIncr.y;
		// 计算Y方向需要跨越的像素数
		numSteps += fast_ceil(origin.y) - fast_floor(goal.y) - 1;
	}

	// 下一个交叉点参数（取X和Y方向的最小值）
	nextDistance = MIN(nextCrossing.x, nextCrossing.y);
	halfDeltaX = 0.5 * delta.x; // 线段X向量的一半（用于计算覆盖面积）

	// 遍历所有需要跨越的像素
	for (step = 0; step < numSteps; ++step) {
		// 计算当前像素的X坐标平均值和Y方向差异
		xAverage = origin.x + (prevDistance + nextDistance) * halfDeltaX;
		yDifference = (nextDistance - prevDistance) * delta.y;
		// 获取当前像素的栅格单元
		cptr = &buf.cells[pixel.y * buf.width + pixel.x];
		cell = *cptr;
		// 更新栅格单元的覆盖累积值和面积
		cell.cover += yDifference;
		xAverage -= (double) pixel.x; // 转换为像素内的相对X坐标（0~1）
		cell.area += (1.0 - xAverage) * yDifference;
		*cptr = cell;

		// 更新上一个交叉点参数
		prevDistance = nextDistance;
		// 判断下一个交叉点在X还是Y方向
		int alongX = nextCrossing.x < nextCrossing.y;
		// 更新当前像素坐标
		pixel.x += alongX ? dir.x : 0;
		pixel.y += alongX ? 0 : dir.y;
		// 更新下一个交叉点参数
		nextCrossing.x += alongX ? crossingIncr.x : 0.0;
		nextCrossing.y += alongX ? 0.0 : crossingIncr.y;
		nextDistance = MIN(nextCrossing.x, nextCrossing.y);
	}

	// 处理最后一个像素
	xAverage = origin.x + (prevDistance + 1.0) * halfDeltaX;
	yDifference = (1.0 - prevDistance) * delta.y;
	cptr = &buf.cells[pixel.y * buf.width + pixel.x];
	cell = *cptr;
	cell.cover += yDifference;
	xAverage -= (double) pixel.x;
	cell.area += (1.0 - xAverage) * yDifference;
	*cptr = cell;
}

/* 绘制轮廓中所有线段到光栅缓冲区。
 * 参数：outl - 轮廓结构体，buf - 光栅缓冲区 */
static void
draw_lines(Outline *outl, Raster buf)
{
	unsigned int i;
	// 遍历所有线段，逐一绘制
	for (i = 0; i < outl->numLines; ++i) {
		Line  line   = outl->lines[i];   // 当前线段
		Point origin = outl->points[line.beg]; // 线段起点
		Point goal   = outl->points[line.end]; // 线段终点
		draw_line(buf, origin, goal);
	}
}

/* 光栅数据后处理（积分栅格单元数据，生成最终8位灰度图像）。
 * 参数：buf - 光栅缓冲区，image - 输出图像缓冲区（uint8_t数组） */
static void
post_process(Raster buf, uint8_t *image)
{
	Cell cell; // 临时存储栅格单元数据
	double accum = 0.0, value; // 累积覆盖值、最终灰度值
	unsigned int i, num; // 循环索引、总像素数
	num = (unsigned int) buf.width * (unsigned int) buf.height; // 总像素数

	// 遍历所有像素
	for (i = 0; i < num; ++i) {
		cell     = buf.cells[i]; // 获取当前栅格单元
		// 计算灰度值（累积覆盖值 + 面积，取绝对值）
		value    = fabs(accum + cell.area);
		value    = MIN(value, 1.0); // 限制最大值为1.0（避免溢出）
		value    = value * 255.0 + 0.5; // 转换为8位灰度（0~255），四舍五入
		image[i] = (uint8_t) value; // 保存到图像缓冲区
		accum   += cell.cover; // 更新累积覆盖值
	}
}

/* 渲染轮廓到图像（包含变换、裁剪、曲线细分、光栅化、后处理）。
 * 参数：outl - 轮廓结构体，transform - 仿射变换矩阵，image - 输出图像结构体
 * 返回：成功返回0，失败返回-1 */
static int
render_outline(Outline *outl, double transform[6], SFT_Image image)
{
	Cell *cells = NULL; // 栅格单元数组
	Raster buf;         // 光栅缓冲区
	unsigned int numPixels; // 总像素数
	
	numPixels = (unsigned int) image.width * (unsigned int) image.height; // 计算总像素数

	// 分配栅格单元数组（栈/堆动态分配，默认栈阈值128x128=16384）
	STACK_ALLOC(cells, Cell, 128 * 128, numPixels);
	if (!cells) {
		return -1;
	}
	memset(cells, 0, numPixels * sizeof *cells); // 初始化栅格单元为0
	buf.cells  = cells;  // 绑定栅格单元数组
	buf.width  = image.width;  // 设置缓冲区宽度
	buf.height = image.height; // 设置缓冲区高度

	// 对轮廓所有点应用仿射变换（缩放、平移等）
	transform_points(outl->numPoints, outl->points, transform);

	// 裁剪点到图像边界（避免绘制超出图像范围的像素）
	clip_points(outl->numPoints, outl->points, image.width, image.height);

	// 细分所有曲线为线段（准备光栅化）
	if (tesselate_curves(outl) < 0) {
		STACK_FREE(cells);
		return -1;
	}

	// 绘制所有线段到光栅缓冲区（计算像素覆盖面积）
	draw_lines(outl, buf);

	// 后处理：将栅格数据转换为8位灰度图像
	post_process(buf, image.pixels);

	// 释放栅格单元数组
	STACK_FREE(cells);
	return 0;
}